package com.example.a_java.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.a_java.entity.LoanContract;
import com.example.a_java.entity.LoanRepaymentPlan;
import com.example.a_java.mapper.LoanRepaymentPlanMapper;
import com.example.a_java.service.LoanContractService;
import com.example.a_java.service.LoanRepaymentPlanService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * 还款计划Service实现�?
 */
@Service
public class LoanRepaymentPlanServiceImpl extends ServiceImpl<LoanRepaymentPlanMapper, LoanRepaymentPlan> implements LoanRepaymentPlanService {
    
    private static final Logger log = LoggerFactory.getLogger(LoanRepaymentPlanServiceImpl.class);
    
    @Autowired
    private LoanContractService contractService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateRepaymentPlan(Long contractId) {
        // 1. 获取合同信息
        LoanContract contract = contractService.getById(contractId);
        if (contract == null) {
            log.error("生成还款计划失败：合同 ID {} 不存在", contractId);
            return false;
        }
        
        // 2. 检查是否已经生成了还款计划
        LambdaQueryWrapper<LoanRepaymentPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LoanRepaymentPlan::getContractId, contractId);
        long count = count(wrapper);
        if (count > 0) {
            // 已经存在还款计划，先删除
            log.info("合同 ID {} 已存在还款计划，先删除旧计划", contractId);
            remove(wrapper);
        }
        
        // 3. 生成还款计划
        List<LoanRepaymentPlan> plans = new ArrayList<>();
        Integer loanTerm = contract.getLoanTerm(); // 贷款期限
        BigDecimal loanAmount = contract.getLoanAmount(); // 贷款金额
        BigDecimal interestRate = contract.getInterestRate().divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP); // 转换为小数
        BigDecimal monthlyRate = interestRate.divide(new BigDecimal("12"), 6, RoundingMode.HALF_UP); // 月利率
        LocalDate startDate = contract.getStartDate(); // 开始日期
        
        // 根据还款方式生成还款计划
        try {
            switch (contract.getRepayMethod()) {
                case 1: // 等额本息
                    generateEqualInstallment(plans, contractId, loanAmount, loanTerm, monthlyRate, startDate);
                    break;
                case 2: // 等额本金
                    generateEqualPrincipal(plans, contractId, loanAmount, loanTerm, monthlyRate, startDate);
                    break;
                case 3: // 先息后本
                    generateInterestFirstPrincipalLast(plans, contractId, loanAmount, loanTerm, monthlyRate, startDate);
                    break;
                case 4: // 一次性还本付息
                    generateBulletRepayment(plans, contractId, loanAmount, loanTerm, monthlyRate, startDate);
                    break;
                default:
                    log.error("生成还款计划失败：不支持的还款方式 {}", contract.getRepayMethod());
                    return false;
            }
            
            // 4. 批量保存还款计划
            boolean result = saveBatch(plans);
            if (result) {
                log.info("合同 ID {} 还款计划生成成功，共 {} 期", contractId, plans.size());
                return true;
            } else {
                log.error("合同 ID {} 还款计划保存失败", contractId);
                return false;
            }
        } catch (Exception e) {
            log.error("生成还款计划时发生异常：{}", e.getMessage(), e);
            throw e; // 抛出异常以触发事务回滚
        }
    }
    
    /**
     * 生成等额本息还款计划
     */
    private void generateEqualInstallment(List<LoanRepaymentPlan> plans, Long contractId, 
                                         BigDecimal loanAmount, Integer loanTerm, 
                                         BigDecimal monthlyRate, LocalDate startDate) {
        // 计算每月还款金额：本�?* 月利�?* (1+月利�?^贷款期限 / ((1+月利�?^贷款期限 - 1)
        BigDecimal temp = BigDecimal.ONE.add(monthlyRate).pow(loanTerm);
        BigDecimal monthlyPayment = loanAmount.multiply(monthlyRate).multiply(temp)
                .divide(temp.subtract(BigDecimal.ONE), 2, RoundingMode.HALF_UP);
        
        BigDecimal principalBalance = loanAmount; // 剩余本金
        
        for (int i = 1; i <= loanTerm; i++) {
            LoanRepaymentPlan plan = new LoanRepaymentPlan();
            plan.setContractId(contractId);
            plan.setTermNo(i);
            plan.setRepayDate(startDate.plusMonths(i));
            
            // 计算每月利息：剩余本�?* 月利�?
            BigDecimal interest = principalBalance.multiply(monthlyRate).setScale(2, RoundingMode.HALF_UP);
            
            // 计算每月本金：月�?- 利息
            BigDecimal principal = monthlyPayment.subtract(interest);
            if (i == loanTerm) {
                // 最后一期，处理精度问题
                principal = principalBalance;
            }
            
            // 更新剩余本金
            principalBalance = principalBalance.subtract(principal);
            
            plan.setPrincipal(principal);
            plan.setInterest(interest);
            plan.setRepayAmount(principal.add(interest));
            plan.setPrincipalBalance(principalBalance);
            plan.setRepayStatus(10); // 未还
            
            plans.add(plan);
        }
    }
    
    /**
     * 生成等额本金还款计划
     */
    private void generateEqualPrincipal(List<LoanRepaymentPlan> plans, Long contractId, 
                                      BigDecimal loanAmount, Integer loanTerm, 
                                      BigDecimal monthlyRate, LocalDate startDate) {
        // 每月等额本金
        BigDecimal monthlyPrincipal = loanAmount.divide(new BigDecimal(loanTerm), 2, RoundingMode.HALF_UP);
        BigDecimal principalBalance = loanAmount; // 剩余本金
        
        for (int i = 1; i <= loanTerm; i++) {
            LoanRepaymentPlan plan = new LoanRepaymentPlan();
            plan.setContractId(contractId);
            plan.setTermNo(i);
            plan.setRepayDate(startDate.plusMonths(i));
            
            // 计算每月利息：剩余本�?* 月利�?
            BigDecimal interest = principalBalance.multiply(monthlyRate).setScale(2, RoundingMode.HALF_UP);
            
            BigDecimal principal;
            if (i == loanTerm) {
                // 最后一期，处理精度问题
                principal = principalBalance;
            } else {
                principal = monthlyPrincipal;
            }
            
            // 更新剩余本金
            principalBalance = principalBalance.subtract(principal);
            
            plan.setPrincipal(principal);
            plan.setInterest(interest);
            plan.setRepayAmount(principal.add(interest));
            plan.setPrincipalBalance(principalBalance);
            plan.setRepayStatus(10); // 未还
            
            plans.add(plan);
        }
    }
    
    /**
     * 生成先息后本还款计划
     */
    private void generateInterestFirstPrincipalLast(List<LoanRepaymentPlan> plans, Long contractId, 
                                                 BigDecimal loanAmount, Integer loanTerm, 
                                                 BigDecimal monthlyRate, LocalDate startDate) {
        BigDecimal principalBalance = loanAmount; // 剩余本金
        BigDecimal monthlyInterest = loanAmount.multiply(monthlyRate).setScale(2, RoundingMode.HALF_UP);
        
        for (int i = 1; i <= loanTerm; i++) {
            LoanRepaymentPlan plan = new LoanRepaymentPlan();
            plan.setContractId(contractId);
            plan.setTermNo(i);
            plan.setRepayDate(startDate.plusMonths(i));
            
            BigDecimal principal = BigDecimal.ZERO;
            BigDecimal interest = monthlyInterest;
            
            // 最后一期还本金
            if (i == loanTerm) {
                principal = loanAmount;
                principalBalance = BigDecimal.ZERO;
            }
            
            plan.setPrincipal(principal);
            plan.setInterest(interest);
            plan.setRepayAmount(principal.add(interest));
            plan.setPrincipalBalance(principalBalance);
            plan.setRepayStatus(10); // 未还
            
            plans.add(plan);
        }
    }
    
    /**
     * 生成一次性还本付息还款计�?
     */
    private void generateBulletRepayment(List<LoanRepaymentPlan> plans, Long contractId, 
                                      BigDecimal loanAmount, Integer loanTerm, 
                                      BigDecimal monthlyRate, LocalDate startDate) {
        // 计算利息：本�?* 年利�?* 贷款期限(�?
        BigDecimal totalInterest = loanAmount.multiply(monthlyRate).multiply(new BigDecimal(loanTerm))
                .setScale(2, RoundingMode.HALF_UP);
        
        LoanRepaymentPlan plan = new LoanRepaymentPlan();
        plan.setContractId(contractId);
        plan.setTermNo(1);
        plan.setRepayDate(startDate.plusMonths(loanTerm));
        plan.setPrincipal(loanAmount);
        plan.setInterest(totalInterest);
        plan.setRepayAmount(loanAmount.add(totalInterest));
        plan.setPrincipalBalance(BigDecimal.ZERO);
        plan.setRepayStatus(10); // 未还
        
        plans.add(plan);
    }
} 
